/*
 * ExplanatoryTextEdit.cpp
 *
 *  Created on: 12.1.2010
 *      Author: apoi
 */

#include "explanatorytextedit.h"

#include <QAbstractTextDocumentLayout>

#ifdef Q_WS_MAEMO_5
#include <QAbstractKineticScroller>
#endif // Q_WS_MAEMO_5

static const int MINIMUM_HEIGHT = 150; // px, about 4 lines of text

ExplanatoryTextEdit::ExplanatoryTextEdit(QWidget *aParent, const QString& aExplanation)
    : QTextEdit(aExplanation, aParent), iExplanation(aExplanation), iDefault(true)
{
    // trac ticket #23
    // XXX: move to QSS?
    document()->setDefaultStyleSheet("a {color: blue;}");

    // needed on N8, otherwise crashes with long posts
    // tries to cache scroll bar to memory and crashes when scroll bar pixmap is too large
    setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);

    // auto-resize
    connect(
            document()->documentLayout(), SIGNAL(documentSizeChanged(const QSizeF &)),
            this, SLOT(updateHeight())
    );

    // auto-scroll
    // XXX: needed? connect(this, SIGNAL(textChanged()), this, SLOT(updateScroll()));
    connect(this, SIGNAL(cursorPositionChanged()), this, SLOT(updateScroll()));
    
    // set text color (to inactive per default, here) at runtime, since setting it using a 
    // stylesheet doesn't work
    setTextColor(QColor(0x84, 0x84, 0x84));
}

ExplanatoryTextEdit::~ExplanatoryTextEdit()
{
}

void ExplanatoryTextEdit::SetExplanation (const QString &text)
{
    iExplanation = text;

    if (iDefault)
        // update
        setPlainText(iExplanation);
}

void ExplanatoryTextEdit::setText(const QString& aValue)
{
    if (aValue.isEmpty()) {
        iDefault = true;

        setPlainText(iExplanation);

    } else {
        iDefault = false;

        setPlainText(aValue);
    }
}

QString ExplanatoryTextEdit::text() const
{
    if (iDefault)
        return QString();

    else
        return toPlainText();
}

void ExplanatoryTextEdit::changeTextColor (const QColor &color)
{
    Q_UNUSED(color);

    // XXX: none of these work!

/*  Breaks cursor  
    setTextColor(color);
    setPlainText(toPlainText());
*/

/*  Doesn't do anything
    QPalette palette = this->palette();
    palette.setColor(QPalette::Text, color);

    setPalette(palette);
    setForegroundRole(QPalette::Text);
*/    

/*  Doesn't do anything
    QString style = QString("QTextEdit { color: %1 }").arg(color.name());

    setStyleSheet(style);
*/    
}

void ExplanatoryTextEdit::focusInEvent(QFocusEvent *e)
{
    if (iDefault) {
        // clear for input
        setPlainText("");

        iDefault = false;
    }

    QTextEdit::focusInEvent(e);

    // active color
    changeTextColor(QColor("black"));
}

void ExplanatoryTextEdit::focusOutEvent(QFocusEvent *e)
{
    if (toPlainText().isEmpty()) {
        // restore default text
        iDefault = true;

        setPlainText(iExplanation);
    }

    QTextEdit::focusOutEvent(e);
    
    // inactive color
    changeTextColor(QColor(0x84, 0x84, 0x84));
}

void ExplanatoryTextEdit::inputMethodEvent (QInputMethodEvent *e)
{
    if (iDefault) {
        // clear to empty to prepare for incoming cursor inserted text
        setPlainText("");

        iDefault = false;
    }

    // insert new text
    QTextEdit::inputMethodEvent(e);
}

void ExplanatoryTextEdit::hideEvent(QHideEvent *)
{
    // Maemo workaround
    clearFocus();
}
    
void ExplanatoryTextEdit::updateHeight ()
{
    // calculate new height for the text entry widget
    int documentHeight = document()->size().height();
    int widgetHeight = documentHeight + (frameRect().height() - contentsRect().height() - 1);

    // resize minimum height to fit content
    setMinimumHeight(qMax(MINIMUM_HEIGHT, widgetHeight));
}
    
void ExplanatoryTextEdit::updateScroll ()
{
/* XXX: Behaviour on Symbian? No QAbstractKineticScroller */
#ifdef Q_WS_MAEMO_5
    // cursor offset
    QRect cursor = cursorRect();

    // current scroll position
    QPoint scrollPosition = pos();

    // find our parent QAbstractScrollArea
    QAbstractScrollArea *scrollArea = NULL;
    QWidget *parent = parentWidget();

    while (parent) {
        // find ScrollArea parent
        if (
                parent->parentWidget() 

                // something weird about widget parents...
            &&  (scrollArea = qobject_cast<QAbstractScrollArea *>(
                    parent->parentWidget()->parentWidget()
                ))
        )
            break;

        // fix coordinates for parent
        scrollPosition = parent->mapToParent(scrollPosition);
        parent = parent->parentWidget();
    }

    if (!scrollArea)
        // not inside a ScrollArea
        return;

    // get the associated KineticScroller
    // XXX: can't we just use QScrollArea::ensureVisible?
    QAbstractKineticScroller *scroller;

    if (!(scroller = scrollArea->property("kineticScroller").value<QAbstractKineticScroller *>()))
        // don't have a kineticScroller
        return;

    // scroll to target
    scroller->ensureVisible(scrollPosition + cursor.center(), 10 + cursor.width(), 2 * cursor.height());
#endif    
}

void ExplanatoryTextEdit::insertText (const QString& text) 
{
    if (iDefault) {
        iDefault = false;

        // replace expl. text
        setPlainText(text);


    } else {
        // at cursor position
        insertPlainText(text);
    }
}
